package com.xjnt.frameworks.core;

import java.lang.reflect.Method;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.StrKit;
import com.xjnt.frameworks.utils.RegularKit;
import com.xjnt.frameworks.web.message.ValidMsg;


public abstract class BaseValidator implements Interceptor {
	
	private Controller controller;
	private Invocation invocation;
	private boolean shortCircuit = false;
	private boolean invalid = false;
	private ValidMsg validMsg = null;
	private String dateFormat = null;
	
	private static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
	
	protected void setShortCircuit(boolean shortCircuit) {
		this.shortCircuit = shortCircuit;
	}
	
	protected void setDateFormat(String dateFormat) {
		this.dateFormat = dateFormat;
	}
	
	public String getDateFormat() {
		return dateFormat != null ? dateFormat : DEFAULT_DATE_PATTERN;
	}
	
	public ValidMsg getValidMsg() {
		if(validMsg == null){
			validMsg = new ValidMsg();
		}
		return validMsg;
	}
	
	@Override
	final public void intercept(Invocation invocation) {
		BaseValidator validator = null;
		try { validator = getClass().newInstance(); }
		catch (InstantiationException e) { throw new RuntimeException(); }
		catch (IllegalAccessException e) { throw new RuntimeException(); }
		
		validator.invocation = invocation;
		validator.controller = invocation.getController();
		
		try { validator.validate(validator.controller); }
		catch (RuntimeException re) {/* short circuit validate need this */}
		
		if( validator.invalid ){
			validator.handleError(validator.controller);
		} else {
			invocation.invoke();
		}
		
	}
	
	/**
	 * Use validateXxx method to validate the parameters of this action.
	 */
	protected abstract void validate(Controller c);
	
	/**
	 * Handle the validate error.
	 * Example:<br>
	 * controller.keepPara();<br>
	 * controller.render("register.html");
	 */
	protected abstract void handleError(Controller c);
	
	/**
	 * Add message when validate failure.
	 */
	protected void addError(String errorKey, String errorMsg) {
		invalid = true;
		getValidMsg().putErrors(errorKey, errorMsg);
		if (shortCircuit) {
			throw new RuntimeException();
		}
	}
	
	/**
	 * Return the controller of this action.
	 */
	protected Controller getController() {
		return controller;
	}
	
	/**
	 * Return the action key of this action.
	 */
	protected String getActionKey() {
		return invocation.getActionKey();
	}
	
	/**
	 * Return the controller key of this action.
	 */
	protected String getControllerKey() {
		return invocation.getControllerKey();
	}
	
	/**
	 * Return the method of this action.
	 */
	protected Method getActionMethod() {
		return invocation.getMethod();
	}
	
	/**
	 * Return view path of this controller.
	 */
	protected String getViewPath() {
		return invocation.getViewPath();
	}
	
	/**
	 * Validate required string.
	 */
	protected void validateRequiredString(String field, String errorKey, String errorMsg) {
		if (StrKit.isBlank(controller.getPara(field)))
			addError(errorKey, errorMsg);
	}
	
	/**
	 * Validate required string for urlPara.
	 */
	protected void validateRequiredString(int index, String errorKey, String errorMsg) {
		if (StrKit.isBlank(controller.getPara(index)))
			addError(errorKey, errorMsg);
	}
	
	/**
	 * Validate required Chinese.
	 */
	protected void validatorIsChinese(String field, String errorKey, String errorMsg){
		String value = controller.getPara(field);
		if(StrKit.notBlank(value)){
			if(!RegularKit.isChinese(value)){
				addError(errorKey, errorMsg);
			}
		} else {
			addError(errorKey, errorMsg);
		}
	}
	
	/**
	 * Validate required Chinese.
	 */
	protected void validatorIsChinese(int index, String errorKey, String errorMsg){
		String value = controller.getPara(index);
		if(StrKit.notBlank(value)){
			if(!RegularKit.isChinese(value)){
				addError(errorKey, errorMsg);
			}
		} else {
			addError(errorKey, errorMsg);
		}
	}
	
	/**
	 * Validate required Chinese and length between min and max.
	 */
	protected void validatorIsChinese(String field, int min, int max, String errorKey, String errorMsg){
		String value = controller.getPara(field);
		if(StrKit.notBlank(value)){
			if(!RegularKit.isChinese(value, min, max)){
				addError(errorKey, errorMsg);
			}
		} else {
			addError(errorKey, errorMsg);
		}
	}
	
	/**
	 * Validate required Chinese and length between min and max.
	 */
	protected void validatorIsChinese(int index, int min, int max, String errorKey, String errorMsg){
		String value = controller.getPara(index);
		if(StrKit.notBlank(value)){
			if(!RegularKit.isChinese(value, min, max)){
				addError(errorKey, errorMsg);
			}
		} else {
			addError(errorKey, errorMsg);
		}
	}
	
	
	/**
	 * Validate required Code.
	 */
	protected void validatorIsCode(String field, String errorKey, String errorMsg){
		String value = controller.getPara(field);
		if(StrKit.notBlank(value)){
			if(!RegularKit.isCode(value)){
				addError(errorKey, errorMsg);
			}
		} else {
			addError(errorKey, errorMsg);
		}
	}
	
	/**
	 * Validate required Code.
	 */
	protected void validatorIsCode(int index, String errorKey, String errorMsg){
		String value = controller.getPara(index);
		if(StrKit.notBlank(value)){
			if(!RegularKit.isCode(value)){
				addError(errorKey, errorMsg);
			}
		} else {
			addError(errorKey, errorMsg);
		}
	}
	
	/**
	 * Validate required Code and length between min and max.
	 */
	protected void validatorIsCode(String field, int min, int max, String errorKey, String errorMsg){
		String value = controller.getPara(field);
		if(StrKit.notBlank(value)){
			if(!RegularKit.isCode(value, min, max)){
				addError(errorKey, errorMsg);
			}
		} else {
			addError(errorKey, errorMsg);
		}
	}
	
	/**
	 * Validate required Code and length between min and max.
	 */
	protected void validatorIsCode(int index, int min, int max, String errorKey, String errorMsg){
		String value = controller.getPara(index);
		if(StrKit.notBlank(value)){
			if(!RegularKit.isCode(value, min, max)){
				addError(errorKey, errorMsg);
			}
		} else {
			addError(errorKey, errorMsg);
		}
	}
}
